package com.theexceptions.todo.view;

import com.theexceptions.todo.controller.TasksController;
import com.theexceptions.todo.model.Task;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.widget.CheckBox;
import android.widget.Toast;

/**
 * An activity that display's the current user's task with any/all applied
 * filters. Corresponds to the view: tasks.xml.
 * 
 * Special thanks to Andrew Lim's quide (bit.ly/KIUFbp).
 * 
 * @author Justian Meyer
 */
public class TasksActivity extends Activity {

	private ListView mainListView;
	private Task[] tasks;
	private ArrayAdapter<Task> listAdapter;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.tasks);
		mainListView = (ListView) findViewById(R.id.mainListView);
		configureListComponents();
	}

	/**
	 * Resets the list and its components to match the filtered list of user
	 * tasks. This method was created as a final attempt to properly refresh the
	 * task list once a new filter was applied.
	 */
	private void configureListComponents() {
		// Populate task list
		tasks = (Task[]) getLastNonConfigurationInstance();
		if (tasks == null) {
			tasks = TasksController.getCurrentUserTasks();
		}

		ArrayList<Task> taskList = new ArrayList<Task>();
		taskList.addAll(Arrays.asList(tasks));

		// Retrieve an arrayAdapter with user's filtered items
		listAdapter = new TaskArrayAdapter(this, taskList);
		mainListView.setAdapter(listAdapter);

		// When item is tapped, bring up a page to edit the item
		mainListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View item,
					int position, long id) {
				Toast.makeText(getApplicationContext(), "[This should bring up an editor]",
						Toast.LENGTH_SHORT).show();
			}
		});
	}

	/**
	 * Holds child view for one row.
	 * 
	 * @author Justian Meyer
	 */
	private static class TaskViewHolder {
		private CheckBox checkBox;
		private TextView textView;

		public TaskViewHolder(TextView textView, CheckBox checkBox) {
			this.checkBox = checkBox;
			this.textView = textView;
		}

		public CheckBox getCheckBox() {
			return checkBox;
		}

		public TextView getTextView() {
			return textView;
		}
	}

	/**
	 * Custom adapter for displaying an array of Task objects.
	 * 
	 * @author Justian Meyer
	 */
	private static class TaskArrayAdapter extends ArrayAdapter<Task> {

		private LayoutInflater inflater;

		/**
		 * Constructs a TaskArrayAdapter
		 * 
		 * @param context
		 * @param taskList
		 */
		public TaskArrayAdapter(Context context, List<Task> taskList) {
			super(context, R.layout.taskrow, R.id.rowTextView, taskList);
			inflater = LayoutInflater.from(context);
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			// Task to display
			Task task = this.getItem(position);

			CheckBox checkBox;
			TextView textView;

			// Create a new row view
			if (convertView == null) {
				convertView = inflater.inflate(R.layout.taskrow, null);

				// Find the child views.
				textView = (TextView) convertView.findViewById(R.id.rowTextView);
				checkBox = (CheckBox) convertView.findViewById(R.id.CheckBox01);

				// Optimization: Tag the row with it's child views, so we don't
				// have to call findViewById() later when we reuse the row.
				convertView.setTag(new TaskViewHolder(textView, checkBox));

				// A quick fix for allowing listener to notify change
				final TaskArrayAdapter adapter = this;

				// If CheckBox is toggled, update the Task it is tagged with.
				checkBox.setOnClickListener(new View.OnClickListener() {
					public void onClick(View v) {
						CheckBox cb = (CheckBox) v;
						Task task = (Task) cb.getTag();
						TasksController.toggleTaskCompleted(task);
						adapter.notifyDataSetChanged();
					}
				});

			} else { // Reuse existing row view
				TaskViewHolder viewHolder = (TaskViewHolder) convertView.getTag();
				checkBox = viewHolder.getCheckBox();
				textView = viewHolder.getTextView();
			}

			// Recolor row based on whether task is completed
			textView.setTextColor(task.isCompleted() ? Color.DKGRAY : Color.WHITE);
			textView.setText(task.toString());

			// Tag the CheckBox with the Task it is displaying, so that we can
			// access the Task in onClick() when the CheckBox is toggled.
			checkBox.setTag(task);

			// Display task data
			checkBox.setChecked(task.isCompleted());
			textView.setText(task.toString());

			return convertView;
		}

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.tasks_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Intent intent;

		switch (item.getItemId()) {
		case R.id.filter:
			intent = new Intent(this, TaskFilterActivity.class);
			startActivityForResult(intent, 2000);
			break;
		case R.id.viewmap:
			intent = new Intent(this, ShowMapActivity.class);
			startActivity(intent);
			break;
		}
		return true;
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == 2000) {
			if (resultCode == Activity.RESULT_OK) {
				configureListComponents();
			}
		} else if (requestCode == 3000) {
			if (resultCode == Activity.RESULT_OK) {
				configureListComponents();
			}
		}
	}

	@Override
	public Object onRetainNonConfigurationInstance() {
		return tasks;
	}

	/**
	 * Switches to AddTaskActivity when "+" button is clicked.
	 * 
	 * @param view
	 */
	public void addTaskButtonClicked(View view) {
		Intent intent = new Intent(view.getContext(), AddTaskActivity.class);
		startActivityForResult(intent, 3000);
	}

	/**
	 * Logs the user out when "logout" button is clicked.
	 * 
	 * @param view
	 */
	public void logoutButtonClicked(View view) {
		TasksController.logout();
		finish();
	}
}
